package com.ct.application.shipping.service.impl;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson.JSON;
import com.ct.application.shipping.model.po.ChuanYuanKuExcelPO;
import com.ct.application.shipping.service.ChuanYuanFenZuService;
import com.ct.application.shipping.service.ChuanYuanKuService;
import com.ct.shipping.orm.ChuanYuanFenZuDO;
import com.ct.shipping.orm.ChuanYuanKuDO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;


@Slf4j
public class ChuanYuanDaoRuListener implements ReadListener<ChuanYuanKuExcelPO> {

    /**
     * 分批读取excel数据，每个批次读取的数量
     */
    private static final int BATCH_COUNT = 500;

    /**
     * 缓存的数据
     */
    private List<ChuanYuanKuExcelPO> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    private ChuanYuanKuService chuanYuanKuService;
    private ChuanYuanFenZuService chuanYuanFenZuService;

    /**
     * 上传的excel文件的头列名
     */
    private String headCellName;

    private Map<String,Boolean> headCellNameMap = new HashMap(){{
        put("船员姓名",true);
        put("英文名",true);
        put("性别",true);
        put("身份号",true);
        put("手机号码",true);
        put("出生日期",true);
        put("船员分组",true);
        put("职位",true);
        put("籍贯",true);
        put("血型",true);
        put("民族",true);
        put("婚姻状况",true);
        put("宗教信仰",true);
        put("船员类型",true);
        put("证书等级",true);
        put("毕业院校",true);
        put("最高学历",true);
        put("专业",true);
        put("英语水平",true);
        put("计算机水平",true);
        put("其他技能",true);
        put("身高",true);
        put("体重",true);
        put("鞋号",true);
        put("其他电话",true);
        put("邮箱",true);
        put("工作服号",true);
        put("紧急联系人",true);
        put("紧急联系人电话",true);
        put("地址",true);
        put("银行卡号",true);
        put("银行户名",true);
        put("开户行",true);
        put("紧急联系人地址",true);
        put("银行国际代码",true);
        put("持有人与船员关系",true);
        put("用途",true);
        put("船员自定义标签",true);
        put("备注",true);
    }};

    public ChuanYuanDaoRuListener(ChuanYuanKuService chuanYuanKuService, ChuanYuanFenZuService chuanYuanFenZuService) {
        this.chuanYuanKuService = chuanYuanKuService;
        this.chuanYuanFenZuService = chuanYuanFenZuService;
    }


    /**
     * 这个每一条数据解析都会来调用
     */
    @Override
    public void invoke(ChuanYuanKuExcelPO data, AnalysisContext context) {
        //log.info("解析到一条数据:{}", JSON.toJSONString(data));
        cachedDataList.add(data);
        // 达到BATCH_COUNT了，需要去查询一次数据库
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    /**
     * 这里会一行行的返回头
     */
    @Override
    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
        ReadCellData<?> head = headMap.get(0);
        String headCellName = head.getStringValue();
        if(StringUtils.isEmpty(headCellName)){
            throw new RuntimeException("文件格式错误,列名不能为空");
        }
        Boolean value = headCellNameMap.get(headCellName);
        if(value == null || !value){
            throw new RuntimeException("文件格式错误,列名不匹配");
        }
        this.headCellName = headCellName;
    }

    /**
     * 所有数据解析完成了 都会来调用
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 这里也要查询数据，确保最后遗留的数据也操作了
        saveData();
    }

    private void saveData(){
        for (ChuanYuanKuExcelPO excelPO : cachedDataList) {
            ChuanYuanKuDO chuanYuanKuDO = null;
            if (StringUtils.isEmpty(excelPO.getShenFenHao())) {
                chuanYuanKuDO = new ChuanYuanKuDO();
                BeanUtils.copyProperties(excelPO, chuanYuanKuDO);
                String fenZu = excelPO.getFenZu();
                if (StringUtils.isNotEmpty(fenZu)) {
                    ChuanYuanFenZuDO fenZuDO = chuanYuanFenZuService.lambdaQuery()
                            .eq(ChuanYuanFenZuDO::getZuMing, fenZu)
                            .last(" limit 1 ").one();
                    if (fenZuDO != null) {
                        chuanYuanKuDO.setFenZuId(fenZuDO.getId());
                    }
                }
                chuanYuanKuService.save(chuanYuanKuDO);
            } else {
                boolean update = false;
                chuanYuanKuDO = chuanYuanKuService.lambdaQuery()
                        .eq(ChuanYuanKuDO::getShenFenHao, excelPO.getShenFenHao())
                        .last(" limit 1 ").one();
                if (chuanYuanKuDO != null) {
                    update = true;
                }else{
                    chuanYuanKuDO = new ChuanYuanKuDO();
                }
                BeanUtils.copyProperties(excelPO, chuanYuanKuDO);
                String fenZu = excelPO.getFenZu();
                if (StringUtils.isNotEmpty(fenZu)) {
                    ChuanYuanFenZuDO fenZuDO = chuanYuanFenZuService.lambdaQuery()
                            .eq(ChuanYuanFenZuDO::getZuMing, fenZu)
                            .last(" limit 1 ").one();
                    if (fenZuDO != null) {
                        chuanYuanKuDO.setFenZuId(fenZuDO.getId());
                    }
                }
                chuanYuanKuDO.setChuShengRiQi(getBirthDateFromIdCard(excelPO.getShenFenHao()));
                chuanYuanKuDO.setNianling(getAgeFromIdCard(excelPO.getShenFenHao()));
                chuanYuanKuDO.setXingBie(getGenderFromIdCard(excelPO.getShenFenHao()));
                if (update) {
                    chuanYuanKuService.updateById(chuanYuanKuDO);
                } else {
                    chuanYuanKuService.save(chuanYuanKuDO);
                }
            }
        }
    }

    public static String getBirthDateFromIdCard(String idCard) {
        if (idCard.length() == 18) {
            String year = idCard.substring(6, 10);
            String month = idCard.substring(10, 12);
            String day = idCard.substring(12, 14);
            return year + "-" + month + "-" + day;
        } else if (idCard.length() == 15) {
            String year = "19" + idCard.substring(6, 8);
            String month = idCard.substring(8, 10);
            String day = idCard.substring(10, 12);
            return year + "-" + month + "-" + day;
        }
        return "";
    }

    public static String getAgeFromIdCard(String idCard) {
        try {
            String birthDateStr = getBirthDateFromIdCard(idCard);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date birthDate = sdf.parse(birthDateStr);
            Calendar cal = Calendar.getInstance();
            cal.setTime(birthDate);
            int birthYear = cal.get(Calendar.YEAR);
            int birthMonth = cal.get(Calendar.MONTH) + 1;
            int birthDay = cal.get(Calendar.DAY_OF_MONTH);

            cal.setTime(new Date());
            int currentYear = cal.get(Calendar.YEAR);
            int currentMonth = cal.get(Calendar.MONTH) + 1;
            int currentDay = cal.get(Calendar.DAY_OF_MONTH);

            int age = currentYear - birthYear;
            if (currentMonth < birthMonth || (currentMonth == birthMonth && currentDay < birthDay)) {
                age--;
            }
            return String.valueOf(age);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return "";
    }

    // 获取性别
    public static String getGenderFromIdCard(String idCard) {
        if (idCard.length() == 18) {
            char genderCode = idCard.charAt(16); // 18位身份证的性别位
            return (genderCode % 2 != 0) ? "男" : "女";
        } else if (idCard.length() == 15) {
            char genderCode = idCard.charAt(14); // 15位身份证的性别位
            return (genderCode % 2 != 0) ? "男" : "女";
        }
        return "";
    }


}
